package ms.jasim.console;

import java.awt.BorderLayout;
import java.awt.Component;
import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import ms.jacrim.framework.ActiveSolution;
import ms.jacrim.framework.Configuration;
import ms.jacrim.pddl.PddlSolution;
import ms.jacrim.pddl.PddlSolution.Action;
import ms.spm.IAppContext;

import org.flexdock.docking.DockingConstants;
import org.flexdock.view.View;

public class AgentTimelineFrame extends JasimDockablePanel {

	private static final long serialVersionUID = 1L;

	private String eventOutput = "timeline/src/webapp/data/events.xml";
	private SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss 'GMT'Z");
	private Timer refreshTimer;

	// private WebBrowser wb;
	private boolean done = false;

	public AgentTimelineFrame(IAppContext context) throws MalformedURLException {
		super(context);
		createContent();
		setText("Agent Timeline");
		refresh();

		refreshTimer = new Timer();
		refreshTimer.schedule(new TimerTask() {

			@Override
			public void run() {
				refresh();
			}

		}, 0, 1000 * 60);
	}

	@Override
	protected Component createFlexFockView() {
		View view = (View) super.createFlexFockView();
		view.setTerritoryBlocked(DockingConstants.CENTER_REGION, true);
		// view.setTitlebar(null);
		return view;
	}

	private void createContent() throws MalformedURLException {
		setLayout(new BorderLayout());
		
	}
	
	
	@Override
	protected void setupContext() {
		super.setupContext();

		Configuration cfg = context.getService(Configuration.class);
		eventOutput = cfg.get("event_output", eventOutput);

		svcJasim.addListener(new JasimClientListener() {
			@Override
			public void notifyListener() {
				refresh();
			}
		});
	}

	private String generateEventData() {
		StringBuilder result = new StringBuilder();
		result.append("<data>\n");

		ActiveSolution sol = svcJasim.getActiveSolution();
		if (sol != null) {
			List<PddlSolution.Action> actions = sol.toArray();
			// sort the actions list according to action's actor
			Collections.sort(actions, new Comparator<PddlSolution.Action>() {
				@Override
				public int compare(Action o1, Action o2) {
					int result = o1.Argument(0).compareToIgnoreCase(o2.Argument(0));
					return result;
				}
			});

			for (PddlSolution.Action act : actions) {
				ActiveSolution.ActionInfo info = sol.findActionInfo(act);
				if (info != null) {
					if ("SATISFIES".equalsIgnoreCase(act.Name())) {
						addSatisfyEvent(result, act, info);
					} else if ("PASSES".equalsIgnoreCase(act.Name())) {
						addPassesEvent(result, act, info);
					}
				}
			}
		}

		result.append("</data>\n");
		return result.toString();
	}

	private void addSatisfyEvent(StringBuilder result, PddlSolution.Action act, ActiveSolution.ActionInfo info) {
		Date end = info.getEnd() != null ? info.getEnd() : new Date();
		String colorStr = info.getEnd() != null ? "color=\"green\"" : "color=\"red\"";
		String description = getActionDescription(act);
		result.append(String.format("<event start=\"%s\" end=\"%s\" title=\"%s\" isDuration=\"true\" %s caption=\"%s\" >%s</event>\n", sdf
				.format(info.getStart()), sdf.format(end), getActionTitle(act), colorStr, description, description));
	}

	private void addPassesEvent(StringBuilder result, PddlSolution.Action act, ActiveSolution.ActionInfo info) {
		if (info.getEnd() != null) {
			String description = getActionDescription(act);
			result.append(String.format("<event start=\"%s\" title=\"%s\" caption=\"%s\">%s</event>\n", sdf.format(info.getEnd()),
					getActionTitle(act), description, description));
		}
	}

	private String getActionDescription(Action act) {
		String result = null;
		if ("PASSES".equalsIgnoreCase(act.Name()))
			result = String.format("%s delegates goal %s to %s", act.Argument(0), act.Argument(2), act.Argument(1));
		else if ("SATISFIES".equalsIgnoreCase(act.Name()))
			result = String.format("%s fulfills goal %s", act.Argument(0), act.Argument(1));
		else if ("AND_DECOMPOSES2".equalsIgnoreCase(act.Name()))
			result = String.format("%s descomposes goal %s to %s and %s", act.Argument(0), act.Argument(1), act.Argument(2), act
					.Argument(2));
		else if ("AND_DECOMPOSES3".equalsIgnoreCase(act.Name()))
			result = String.format("%s descomposes goal %s to %s, %s and %s", act.Argument(0), act.Argument(1), act.Argument(2), act
					.Argument(2), act.Argument(3));
		return result;
	}

	private String getActionTitle(Action act) {
		String result = null;
		if ("PASSES".equalsIgnoreCase(act.Name()))
			result = String.format("%s delegates %s", act.Argument(0), act.Argument(2), act.Argument(1));
		else if ("SATISFIES".equalsIgnoreCase(act.Name()))
			result = String.format("%s fulfills %s", act.Argument(0), act.Argument(1));
		else if ("AND_DECOMPOSES2".equalsIgnoreCase(act.Name()))
			result = String.format("%s descomposes %s", act.Argument(0), act.Argument(1), act.Argument(2), act.Argument(2));
		else if ("AND_DECOMPOSES3".equalsIgnoreCase(act.Name()))
			result = String
					.format("%s descomposes %s", act.Argument(0), act.Argument(1), act.Argument(2), act.Argument(2), act.Argument(3));
		return result;
	}

	private void refresh() {
		try {
			System.out.println("refreshing timeline...");
			FileWriter fw = new FileWriter(eventOutput, false);
			fw.write(generateEventData());
			fw.close();
			// if (wb != null)
			// wb.executeScript("reloadData();");
		} catch (IOException e) {
			// e.printStackTrace();
		}
	}

	public void showBrowser() {
		// wb = new WebBrowser();
		// add(wb, BorderLayout.CENTER);
		// Button b = new Button();
		// b.setLabel("ABC");
		// add(b, BorderLayout.CENTER);
	}

	
}
